// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <cstdio>
#include <map>
#include <memory>
#include <set>
#include <string>

#include <rapidjson/document.h>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/lmax_digital/symbology/currency.h"
#include "coin2/exchange/lmax_digital/symbology/product.h"

namespace coin2::exchange::lmax_digital::order_v1 {

constexpr auto BUY = '1';
constexpr auto SELL = '2';
constexpr auto MSG_TYPE_SESSION_REJECT = "3";
constexpr auto MSG_TYPE_EXECUTION_REPORT = "8";
constexpr auto MSG_TYPE_ORDER_CANCEL_REJECT = "9";
constexpr auto EXEC_TYPE_NEW_ORDER = '0';
constexpr auto EXEC_TYPE_PARTIALLY_FILL = '1';
constexpr auto EXEC_TYPE_FILL = '2';
constexpr auto EXEC_TYPE_CANCELED = '4';
constexpr auto EXEC_TYPE_REPLACE = '5';
constexpr auto EXEC_TYPE_REJECTED = '8';
constexpr auto ORD_STATUS_NEW_ORDER = '0';
constexpr auto ORD_STATUS_PARTIALLY_FILLED = '1';
constexpr auto ORD_STATUS_FILLED = '2';
constexpr auto ORD_STATUS_CANCELLED_ORDER = '4';
constexpr auto ORD_STATUS_REPLACED_ORDER = '5';

class LmaxdigitalParser : public base::order::BaseParser {
 public:
  const ParseResult& ParseRawMessage(const RawMessage& msg) override;
  AccountBalance ParseBalance(const JsonValue& doc) override;
  bool ParseRawBalance(const JsonValue& doc, RawBalanceMap* raw_balance_map);

 private:
  void ParseFixMessage(const RawMessage& msg);
  ProductOrderBundle ParseRestOrderInfoList(const JsonValue& data);
  coin::proto::ProductOrderElement ParseRestOrderInfo(const JsonValue& data);
  void ParseFixSubmitResponse(const FIX::Message& message);
  void ParseFixCancelResponse(const FIX::Message& message);
  void ParseFixFillInfo(const FIX::Message& message);
  void ParseFixOrderInfo(const FIX::Message& message);
  void ParseRestAccountBalance();
  auto ParseAuthToken(const JsonValue& doc) -> std::string;
  void ParseRestAuthToken();

  template <class T>
  inline std::optional<int64_t> ToInt64(T&& val) const {
    try {
      return stoll(val);
    } catch (std::exception& ex) {
      return {};
    }
  }
};

}  // namespace coin2::exchange::lmax_digital::order_v1
